#include "netclient.h"
#include <QNetworkReply>
#include "../model/data.h"
#include <QWebSocket>
#include "../model/datacenter.h"


using namespace model;
network::NetClient::NetClient(model::DataCenter *dataCenter)
    :dataCenter(dataCenter)
{

}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void network::NetClient::initWebSocket()
{
    //1.准备好相关信号槽
    connect(&webSocketClient,&QWebSocket::connected,this,[=](){
        LOG() << "webSocket 连接成功";
        this->sendAuth();   //发送身份验证
    });

    connect(&webSocketClient, &QWebSocket::disconnected, this, [=]() {
        LOG() << "websocket 连接断开!";
    });

    connect(&webSocketClient, &QWebSocket::errorOccurred, this, [=](QAbstractSocket::SocketError error) {
        LOG() << "websocket 连接出错!" << error;
    });

    connect(&webSocketClient, &QWebSocket::textMessageReceived, this,[=](const QString& message) {
        LOG() << "websocket 收到文本消息!" << message;
    });
    connect(&webSocketClient,&QWebSocket::binaryMessageReceived,this,[=](const QByteArray& byteArray){
        LOG() << "[websocket] 收到二进制消息" << byteArray.length();
        my::NotifyMessage notifyMessage;
        notifyMessage.deserialize(&this->serializer,byteArray);
        handleWsResponse(notifyMessage);
    });

    //2.真正与服务器建立连接
    webSocketClient.open(WEBSOCKER_URL);

}

void network::NetClient::sendAuth()
{
    my::ClientAuthenticationReq req;

    req.setRequestId(makeRequestID());
    req.setSessionId(dataCenter->getLoginSessionId());

    QByteArray body = req.serialize(&serializer);
    webSocketClient.sendBinaryMessage(body);

    LOG() << "[ws]身份认证 requestID = " << req.requestId() << "loginSessionId = " << req.sessionId();

}

QString network::NetClient::makeRequestID()
{
    return  "R" + QUuid::createUuid().toString().sliced(25,12);    //仅取部分
}




//测试网络连接
void network::NetClient::pingHttp()
{
    QNetworkRequest httpReq;

    httpReq.setUrl(HTTP_URL + "/ping");

    //发送请求，获取响应
    QNetworkReply* httpRes = httpClient.get(httpReq);

    //响应不一定立即返回，需要添加信号槽处理
    connect(httpRes,&QNetworkReply::finished,this,[=](){
        //此时，请求已经返回了响应
        if(httpRes->error() != QNetworkReply::NoError)
        {
            //请求失败
            LOG() << "http 请求失败" << httpRes->errorString();
            httpRes->deleteLater();
            return;
        }

        //正确的响应
        QByteArray body = httpRes->readAll();
        LOG() << "收到Http响应，响应内容：" << body;
        httpRes->deleteLater();
    });
}

QNetworkReply* network::NetClient::sendHttpRequest(const QString& apiPath,const QByteArray& body)
{
    QNetworkRequest httpReq;
    httpReq.setUrl(HTTP_URL + apiPath); //约定好的路由入口
    httpReq.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-protobuf");
    //发送
    QNetworkReply* httpResp = httpClient.post(httpReq,body);
    return httpResp;
}

void network::NetClient::handleWsResponse(const my::NotifyMessage& notifyMessage)
{
    if(notifyMessage.notifyType() == my::NotifyTypeGadget::NotifyType::CHAT_MESSAGE_NOTIFY)
    {
        //1.收到消息，把pb中的消息转换成客户端自己的message
        MessageInfo message;
        message.load(notifyMessage.newMessageInfo().messageInfo());
        //2.针对自己的message进一步处理
        handleWsMessage(message);
    }
    else if(notifyMessage.notifyType() == my::NotifyTypeGadget::NotifyType::CHAT_SESSION_CREATE_NOTIFY)
    {
        ChatSessionInfo chatSessionInfo;
        chatSessionInfo.load(notifyMessage.newChatSessionInfo().chatSessionInfo());
        handleWsChatSessionCreate(chatSessionInfo);
    }
    else if(notifyMessage.notifyType() == my::NotifyTypeGadget::NotifyType::FRIEND_ADD_APPLY_NOTIFY)
    {
        //收到消息，将其转换为自己的userInfo
        UserInfo userInfo;
        userInfo.load(notifyMessage.friendAddApply().userInfo());
        //进一步处理
        handleWsApplyFriend(userInfo);
    }
    else if(notifyMessage.notifyType() == my::NotifyTypeGadget::NotifyType::FRIEND_ADD_PROCESS_NOTIFY)
    {
        UserInfo userInfo;
        userInfo.load(notifyMessage.friendProcessResult().userInfo());
        bool agree = notifyMessage.friendProcessResult().agree();
        handleWsApplyFriendProcess(userInfo,agree);
    }
    else if(notifyMessage.notifyType() == my::NotifyTypeGadget::NotifyType::FRIEND_REMOVE_NOTIFY)
    {
        const QString userId = notifyMessage.friendRemove().userId();
        handleWsRemoveFriend(userId);
    }
}

void network::NetClient::handleWsMessage(const model::MessageInfo message)
{
    QList<model::MessageInfo>* messageList = dataCenter->getRecentMessageList(message.sessionId);
    //由于近期消息列表，是按需加载的
    //当前消息对应的会话列表，可能未被加载，本地可能不存在
    if(messageList == nullptr)
    {
        //1.本地不存在，通过网络加载

        //会话列表，需要更新
        connect(dataCenter,&model::DataCenter::getRecentMessageDoneNoUi,this,&NetClient::receiveMessage,Qt::UniqueConnection);

        dataCenter->getRecentMessageAsync(message.sessionId,false);
    }
    else
    {
        //2.从本地加载,直接将当前收到的消息尾插即可
        messageList->push_back(message);
        this->receiveMessage(message.sessionId);
    }
}

void network::NetClient::handleWsRemoveFriend(const QString &userId)
{
    dataCenter->removeFriend(userId);
    emit dataCenter->deleteFriendDone();
}

void network::NetClient::handleWsApplyFriend(const model::UserInfo &userInfo)
{
    //1.将申请人添加到好友申请列表
    QList<model::UserInfo>* applyList = dataCenter->getApplyList();
    if(applyList == nullptr)
    {
        LOG() << "好友申请列表为nullptr";
        return;
    }
    //2.添加在前面
    applyList->push_front(userInfo);
    //3.通知界面更新
    emit dataCenter->receiveFriendApplyDone();
    Toast::showMessage("收到一条好友申请");
}

void network::NetClient::handleWsApplyFriendProcess(const model::UserInfo userInfo, bool agree)
{
    if(agree)
    {
        //对方同意了申请，将其添加到好友列表
        QList<UserInfo>* friendList = dataCenter->getFriendList();
        if(friendList == nullptr)
        {
            LOG() << "friendList == nullptr";
            return;
        }
        friendList->push_front(userInfo);
        emit dataCenter->recevieFriendApplyProcessDone(userInfo.nickName,agree);
    }
    else
    {
        emit dataCenter->recevieFriendApplyProcessDone(userInfo.nickName,agree);
    }
}

void network::NetClient::handleWsChatSessionCreate(const model::ChatSessionInfo &chatSessionInfo)
{
    //将这个chatSessionInfo,添加到会话列表中即可
    QList<ChatSessionInfo>* chatSessionList = dataCenter->getChatSessionList();
    if(chatSessionList == nullptr)
    {
        LOG() << "会话列表 chatSessionList == nullptr";
        return;
    }

    //将新的会话添加到会话列表头部
    chatSessionList->push_front(chatSessionInfo);
    //发送信号，通知界面更新
    emit dataCenter->receiveSessionCreateDone();
}

//网络通信，获取用户个人头像
void network::NetClient::getMyself(const QString& loginSessionId)
{
    //1. 构造http请求的 body部分
    my::GetUserInfoReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    QByteArray body = pbReq.serialize(&this->serializer);
    LOG() << "[获取个人信息] requestId = " << pbReq.requestId() << " loginSessionId = " << pbReq.sessionId();

    //2.构建http请求，并发送出去
    QNetworkReply* httpResp = sendHttpRequest("/service/user/get_user_info",body);

    //3.通过信号槽，获取到当前的响应，finished信号表示响应已经返回到客户端
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        // a)处理响应对象
        bool ok = true;
        QString reason;
        auto pbResp = handleHttpResponse<my::GetUserInfoRsp>(httpResp,ok,reason);

        // b) 判断响应是否出错
        if(!ok)
        {
            LOG() << "[获取个人信息] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }

        // c) 将响应的数据，保存到DataCenter中
        dataCenter->resetMyself(pbResp);

        // d) 通知调用逻辑，响应已经处理完毕
        emit dataCenter->getMyselfDone();

        LOG() << "[获取个人信息] 响应处理完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::getFriendList(const QString &loginSessionId)
{
    //1. 构造http请求的 body部分
    my::GetFriendListReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    QByteArray body = pbReq.serialize(&this->serializer);
    LOG() << "[获取好友列表] requestId = " << pbReq.requestId() << " loginSessionId = " << pbReq.sessionId();
    //2.发送http请求
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/get_friend_list",body);

    //3.关联信号槽，处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::GetFriendListRsp>(httpResp,ok,reason);

        if(!ok)
        {
            LOG() << "[获取好友列表] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }
        //保存结果
        dataCenter->resetFriendList(pbResp);

        //发送信号
        emit dataCenter->getFriendListDone();

        LOG() << "[获取好友列表] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::getChatSessionList(const QString &loginSessionId)
{
    //1.构造http请求的 body部分
    my::GetChatSessionListReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    QByteArray body = pbReq.serialize(&this->serializer);
    LOG() << "[获取会话列表] requestId = " << pbReq.requestId() << " loginSessionId = " << pbReq.sessionId();

    //2.构建http请求，并发送出去
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/get_chat_session_list",body);

    //3.关联信号槽，处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::GetChatSessionListRsp>(httpResp,ok,reason);

        if(!ok)
        {
            LOG() << "[获取会话列表] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }
        //保存结果
        dataCenter->resetChatSessionLIst(pbResp);

        //发送信号
        emit dataCenter->getChatSessionListDone();

        LOG() << "[获取会话列表] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::getApplyList(const QString &loginSessionId)
{
    //1.构造http请求的 body部分
    my::GetPendingFriendEventListReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    QByteArray body = pbReq.serialize(&this->serializer);
    LOG() << "[获取好友申请列表] requestId = " << pbReq.requestId() << " loginSessionId = " << pbReq.sessionId();

    //2.构建http请求，并发送出去
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/get_pending_friend_events",body);

    //3.关联信号槽，处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::GetPendingFriendEventListRsp>(httpResp,ok,reason);

        if(!ok)
        {
            LOG() << "[获取好友申请列表] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }

        //保存结果
        dataCenter->resetApplyList(pbResp);

        //发送信号
        emit dataCenter->getAppalListDone();

        LOG() << "[获取好友申请列表] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::getRecentMessage(const QString &loginSessionId, const QString &chatSessionId,bool updateUi)
{
    //1.构造http请求的 body部分
    my::GetRecentMsgReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setMsgCount(50);  //固定获取最近的50条
    pbReq.setChatSessionId(chatSessionId);

    QByteArray body = pbReq.serialize(&this->serializer);
    LOG() << "[获取最近消息列表] requestId = " << pbReq.requestId() << " loginSessionId = " << pbReq.sessionId()
          << "chatSessionId= " << pbReq.chatSessionId();

    //2.构建http请求，并发送出去
    QNetworkReply* httpResp = sendHttpRequest("/service/message_storage/get_recent",body);

    //3.关联信号槽，处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::GetRecentMsgRsp>(httpResp,ok,reason);

        if(!ok)
        {
            LOG() << "[获取最近消息列表] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }

        //保存结果
        dataCenter->resetRecentMessageList(chatSessionId,pbResp);
        if(updateUi)
        {
            //发送信号
            emit dataCenter->getRecentMessageDone(chatSessionId);
        }
        else
        {
            emit dataCenter->getRecentMessageDoneNoUi(chatSessionId);
        }

        LOG() << "[获取最近消息列表] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::sendMessage(const QString &loginSessionId,
                                     const QString &chatSessionId,
                                     const model::MessageType messageType,
                                     const QByteArray &content,
                                     const QString extraInfo)
{
    //1.构造http请求的 body部分
    my::NewMessageReq pbReq;
    //构造MessageContent
    my::MessageContent messageContent;
    if(messageType == model::MessageType::TEXT_TYPE)
    {
        messageContent.setMessageType(my::MessageTypeGadget::STRING);
        my::StringMessageInfo stringMessageInfo;
        stringMessageInfo.setContent(content);
        messageContent.setStringMessage(stringMessageInfo);
    }
    else if(messageType == model::MessageType::IMAGE_TYPE)
    {
        LOG() << "network::NetClient::sendMessage--------------";
        messageContent.setMessageType(my::MessageTypeGadget::IMAGE);
        my::ImageMessageInfo imageMessageInfo;
        imageMessageInfo.setFileId("");    //fileId是文件在服务器存储的时候，生成的id
        imageMessageInfo.setImageContent(content);
        messageContent.setImageMessage(imageMessageInfo);
    }
    else if(messageType == model::MessageType::FILE_TYPE)
    {
        messageContent.setMessageType(my::MessageTypeGadget::FILE);
        my::FileMessageInfo fileMessageInfo;
        fileMessageInfo.setFileId("");    //fileId是文件在服务器存储的时候，生成的id
        fileMessageInfo.setFileSize(content.size());
        fileMessageInfo.setFileName(extraInfo);
        fileMessageInfo.setFileContents(content);
        messageContent.setFileMessage(fileMessageInfo);
    }
    else if(messageType == model::MessageType::SPEECH_TYPE)
    {
        messageContent.setMessageType(my::MessageTypeGadget::SPEECH);
        my::SpeechMessageInfo speechMessageInfo;
        speechMessageInfo.setFileId("");    //fileId是文件在服务器存储的时候，生成的id
        speechMessageInfo.setFileContents(content);
        messageContent.setSpeechMessage(speechMessageInfo);
    }
    else
    {
        LOG() << "错误的消息类型，type : " << messageType;
    }

    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setChatSessionId(chatSessionId);
    pbReq.setMessage(messageContent);

    //2.序列化
    QByteArray body = pbReq.serialize(&this->serializer);
    LOG() << "[发送消息] requestId = " << pbReq.requestId() << " loginSessionId = " << pbReq.sessionId()
          << "chatSessionId= " << pbReq.chatSessionId() << "messageType: " << messageType;
    //3.发送http请求
    QNetworkReply* httpResp = sendHttpRequest("/service/message_transmit/new_message",body);

    //4.处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::NewMessageRsp>(httpResp,ok,reason);

        if(!ok)
        {
            LOG() << "[获取最近消息列表] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }

        //保存结果(此处只需要记录“成功/失败”，不需要reset)

        //发送信号
        emit dataCenter->sendMessageDone(messageType,content,extraInfo);

        LOG() << "[发送消息] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::receiveMessage(const QString &chatSessionId)
{
    //1.如果是当前会话，需要在消息展示区显示，并且在会话列表中显示
    if(chatSessionId == dataCenter->getCurrentSessionId())
    {
        const MessageInfo& lastMessage = dataCenter->getRecentMessageList(chatSessionId)->back();
        //通过信号，让netClient模块，通知消息显示区进行显示
        emit dataCenter->receiveMessageDone(lastMessage);
    }
    else
    {
        //2.如果不是当前会话，仅需要在会话列表中显示(更新未读消息数目)
        dataCenter->addUnread(chatSessionId);
    }

    //统一更新会话列表预览
    emit dataCenter->updateLastMessage(chatSessionId);
    Toast::showMessage("收到一条消息");
}

void network::NetClient::changeNickName(const QString &loginSessionId, const QString &nickName)
{
    //1.构造http请求的 body部分
    my::SetUserNicknameReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setNickname(nickName);

    QByteArray body = pbReq.serialize(&this->serializer);
    LOG() << "[修改消息昵称] requestId = " << pbReq.requestId() << " loginSessionId = " << pbReq.sessionId()
          << "nickName = " << pbReq.nickname();

    //2.构建http请求，并发送出去
    QNetworkReply* httpResp = sendHttpRequest("/service/user/set_nickname",body);

    //3.关联信号槽，处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::SetUserNicknameRsp>(httpResp,ok,reason);

        if(!ok)
        {
            LOG() << "[修改消息昵称] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }
        //4.保存
        dataCenter->resetNickName(nickName);

        //5.发送信号
        emit dataCenter->changeNickNameDone();

        LOG() << "[修改消息昵称] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::changeDesc(const QString &loginSessionId, const QString &desc)
{
    //1.构造http请求的 body部分
    my::SetUserDescriptionReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setDescription(desc);

    QByteArray body = pbReq.serialize(&this->serializer);
    LOG() << "[修改个性签名] requestId = " << pbReq.requestId() << " loginSessionId = " << pbReq.sessionId()
          << "nickName = " << pbReq.description();

    //2.构建http请求，并发送出去
    QNetworkReply* httpResp = sendHttpRequest("/service/user/set_description",body);

    //3.关联信号槽，处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::SetUserDescriptionRsp>(httpResp,ok,reason);

        if(!ok)
        {
            LOG() << "[修改个性签名] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }
        //4.保存
        dataCenter->resetDesc(desc);

        //5.发送信号
        emit dataCenter->changeDescDone();

        LOG() << "[修改个性签名] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::getVerifyCode(const QString &phone)
{
    //1.构造http请求的 body部分
    my::PhoneVerifyCodeReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setPhoneNumber(phone);

    QByteArray body = pbReq.serialize(&this->serializer);
    LOG() << "[获取手机验证码] requestId = " << pbReq.requestId()<< "phone = " << pbReq.phoneNumber();

    //2.构建http请求，并发送出去
    QNetworkReply* httpResp = sendHttpRequest("/service/user/get_phone_verify_code",body);

    //3.关联信号槽，处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::PhoneVerifyCodeRsp>(httpResp,ok,reason);

        if(!ok)
        {
            LOG() << "[获取手机验证码] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }
        //4.保存
        dataCenter->resetVerifyCodeId(pbResp->verifyCodeId());

        //5.发送信号
        emit dataCenter->getVerifyCodeDone();

        LOG() << "[获取手机验证码] 响应接收完毕，requestId = " << pbReq.requestId()  << "verifyCodeId = " << pbResp->verifyCodeId();
    });
}

void network::NetClient::changePhone(const QString &loginSessionId, const QString &phone, const QString &verifyCodeId, const QString &verifyCode)
{
    //1.构造http请求的 body部分
    my::SetUserPhoneNumberReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setPhoneNumber(phone);
    pbReq.setPhoneVerifyCode(verifyCode);
    pbReq.setPhoneVerifyCodeId(verifyCodeId);
    pbReq.setSessionId(loginSessionId);

    QByteArray body = pbReq.serialize(&this->serializer);
    LOG() << "[修改手机号] requestId=" << pbReq.requestId()
          << " phoneNumber=" << pbReq.phoneNumber()
          << " verifyCodeId=" << pbReq.phoneVerifyCodeId()
          << " verifyCode=" << pbReq.phoneVerifyCode()
            << "loginSessinId" << pbReq.sessionId();

    //2.构建http请求，并发送出去
    QNetworkReply* httpResp = sendHttpRequest("/service/user/set_phone",body);

    //3.关联信号槽，处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){

        // LOG() << "设置手机收到响应------------";
        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::SetUserPhoneNumberRsp>(httpResp,ok,reason);

        if(!ok)
        {
            LOG() << "[修改⼿机号] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }
        //4.保存
        dataCenter->resetPhone(phone);

        //5.发送信号
        emit dataCenter->changePhoneDone();

        LOG() << "[获取手机验证码] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::changeAvatar(const QString &loginSessionId, const QByteArray &avatar)
{
    //1.构建请求
    my::SetUserAvatarReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setAvatar(avatar);
    QByteArray body = pbReq.serialize(&this->serializer);

    LOG() << "[修改头像] requestId=" << pbReq.requestId()
          << "loginSessinId" << pbReq.sessionId();

    //2.构建http请求，并发送出去
    QNetworkReply* httpResp = sendHttpRequest("/service/user/set_avatar",body);

    //3.关联信号槽，处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){

        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::SetUserAvatarRsp>(httpResp,ok,reason);

        if(!ok)
        {
            LOG() << "[修改头像] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }
        //4.保存
        dataCenter->resetAvatar(avatar);

        //5.发送信号
        emit dataCenter->changeAvatarDone();

        LOG() << "[修改头像] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::deleteFriend(const QString &loginSessionId, const QString &userId)
{
    //1.构建请求
    my::FriendRemoveReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setPeerId(userId);
    QByteArray body = pbReq.serialize(&this->serializer);

    LOG() << "[删除好友] requestId=" << pbReq.requestId()
          << "loginSessinId" << pbReq.sessionId()
          << "peerId" << pbReq.peerId();

    //2.构建http请求，并发送出去
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/remove_friend",body);

    //3.关联信号槽，处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::FriendRemoveRsp>(httpResp,ok,reason);
        if(!ok)
        {
            LOG() << "[删除好友] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }
        //4.保存
        dataCenter->removeFriend(userId);

        //5.发送信号
        emit dataCenter->deleteFriendDone();

        LOG() << "[删除好友] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::applyFriend(const QString &loginSessionId, const QString &userId)
{
    my::FriendAddReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setRespondentId(userId);

    LOG() << "[添加好友] "
          << "requestId = " << pbReq.requestId()
          << " loginSessionId = " << pbReq.sessionId()
          << "respondentId = " << pbReq.respondentId() ;

    QByteArray body = pbReq.serialize(&serializer);

    //2.构建http请求，并发送出去
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/add_friend_apply",body);

    //3.关联信号槽，处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::FriendAddRsp>(httpResp,ok,reason);
        if(!ok)
        {
            LOG() << "[添加好友] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }
        //4.保存,此处不需要

        //5.发送信号
        emit dataCenter->applyFriendDone();

        LOG() << "[添加好友] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::agreeFriendApply(const QString &loginSessionId, const QString &userId)
{
    my::FriendAddProcessReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setAgree(true);
    pbReq.setApplyUserId(userId);
    pbReq.setNotifyEventId("");

    LOG() << "[同意好友申请] "
          << "requestId = " << pbReq.requestId()
          << " loginSessionId = " << pbReq.sessionId()
          << "applierID = " << pbReq.applyUserId() ;

    QByteArray body = pbReq.serialize(&serializer);

    //2.构建http请求，并发送出去
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/add_friend_process",body);

    //3.关联信号槽，处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::FriendAddProcessRsp>(httpResp,ok,reason);
        if(!ok)
        {
            LOG() << "[同意好友申请] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }
        //4.将对应的好友从申请列表中删除，在好友列表中添加
        UserInfo userInfo = dataCenter->removeFriendApply(userId);
        QList<UserInfo>* friendList = dataCenter->getFriendList();
        friendList->push_front(userInfo);

        //5.发送信号
        emit dataCenter->agreeFriendApplyDone();

        LOG() << "[同意好友申请] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::rejectFriendApply(const QString &loginSessionId, const QString &userId)
{
    my::FriendAddProcessReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setAgree(false);
    pbReq.setApplyUserId(userId);
    pbReq.setNotifyEventId("");

    LOG() << "[拒绝好友申请] "
          << "requestId = " << pbReq.requestId()
          << " loginSessionId = " << pbReq.sessionId()
          << "applierID = " << pbReq.applyUserId() ;

    QByteArray body = pbReq.serialize(&serializer);

    //2.构建http请求，并发送出去
    QNetworkReply* httpResp = sendHttpRequest("/service/friend/add_friend_process",body);

    //3.关联信号槽，处理响应
    connect(httpResp,&QNetworkReply::finished,this,[=](){
        bool ok;
        QString reason;
        auto pbResp = handleHttpResponse<my::FriendAddProcessRsp>(httpResp,ok,reason);
        if(!ok)
        {
            LOG() << "[拒绝好友申请] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }

        //4.从申请列表删除
        dataCenter->removeFriendApply(userId);

        //5.发送信号
        emit dataCenter->rejectFriendApplyDone();

        LOG() << "[拒绝好友申请] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::createGroupChatSession(const QString &loginSessionId, const QList<QString> &userIdList)
{
    //1.构造请求body
    my::ChatSessionCreateReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setChatSessionName("新的群聊");
    pbReq.setMemberIdList(userIdList);

    QByteArray body = pbReq.serialize(&serializer);

    LOG() << "[创建群聊会话]"
          << " requestId = " << pbReq.requestId()
          << " loginSessionId = " << pbReq.sessionId()
          << " userIdList = " << pbReq.memberIdList();
    //2.发送http请求
    QNetworkReply* resp = this->sendHttpRequest("/service/friend/create_chat_session",body);
    //3.处理响应
    connect(resp,&QNetworkReply::finished,this,[=](){
        bool ok = true;
        QString reason;
        auto pbResp = this->handleHttpResponse<my::ChatSessionCreateRsp>(resp,ok,reason);
        if(!ok)
        {
            LOG() << "[创建群聊会话] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }

        //往dataCenter中存储数据，由于此处创建好的会话，是wb推送的
        //所以在这里无需更新dataCenter,后续通过wb的逻辑更新即可

        //通知调用者，响应处理完毕
        emit dataCenter->createGroupChatSessionDone();

        LOG() << "[创建群聊会话] 响应接收完毕，requestId = " << pbReq.requestId();
    });

}

void network::NetClient::getMemberList(const QString &loginSessionId, const QString &currentSessionId)
{
    //1.构造请求body
    my::GetChatSessionMemberReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setChatSessionId(currentSessionId);

    QByteArray body = pbReq.serialize(&serializer);

    LOG() << "[获取群聊会话成员列表]"
          << " requestId = " << pbReq.requestId()
          << " loginSessionId = " << pbReq.sessionId()
          << " chatSessionId = " << pbReq.chatSessionId();
    //2.发送http请求
    QNetworkReply* resp = this->sendHttpRequest("/service/friend/get_chat_session_member",body);
    //3.处理响应
    connect(resp,&QNetworkReply::finished,this,[=](){
        bool ok = true;
        QString reason;
        auto pbResp = this->handleHttpResponse<my::GetChatSessionMemberRsp>(resp,ok,reason);
        if(!ok)
        {
            LOG() << "[获取群聊会话成员列表] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }

        //记录结果
        dataCenter->resetMemberList(currentSessionId,pbResp->memberInfoList());

        //通知调用者，响应处理完毕
        emit dataCenter->getMemberListDone(currentSessionId);

        LOG() << "[创建群聊会话] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::searchUser(const QString &loginSessionId, const QString &searchKey)
{
    //1.构造请求body
    my::FriendSearchReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setSearchKey(searchKey);

    QByteArray body = pbReq.serialize(&serializer);

    LOG() << "[搜索用户]请求"
          << " requestId = " << pbReq.requestId()
          << " loginSessionId = " << pbReq.sessionId()
          << " searchKey = " << pbReq.searchKey();
    //2.发送http请求
    QNetworkReply* resp = this->sendHttpRequest("/service/friend/search_friend",body);
    //3.处理响应
    connect(resp,&QNetworkReply::finished,this,[=](){
        bool ok = true;
        QString reason;
        auto pbResp = this->handleHttpResponse<my::FriendSearchRsp>(resp,ok,reason);
        if(!ok)
        {
            LOG() << "[搜索用户] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }

        //记录结果
        dataCenter->resetSearchUserResult(pbResp->userInfo());

        //通知调用者，响应处理完毕
        emit dataCenter->searchUserDone();

        LOG() << "[搜索用户] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::getHistoryMessage(const QString &loginSessionId, const QString &currentChatSessionId, const QString &searchKey)
{
    //1.构造请求body
    my::MsgSearchReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setSearchKey(searchKey);
    pbReq.setChatSessionId(currentChatSessionId);

    QByteArray body = pbReq.serialize(&serializer);

    LOG() << "[通过关键字搜索历史记录]请求"
          << " requestId = " << pbReq.requestId()
          << " loginSessionId = " << pbReq.sessionId()
          << " currentChatSessionId = " << pbReq.chatSessionId()
          << " searchKey = " << pbReq.searchKey();

    //2.发送http请求
    QNetworkReply* resp = this->sendHttpRequest("/service/message_storage/search_history",body);
    //3.处理响应
    connect(resp,&QNetworkReply::finished,this,[=](){
        bool ok = true;
        QString reason;
        auto pbResp = this->handleHttpResponse<my::MsgSearchRsp>(resp,ok,reason);
        if(!ok)
        {
            LOG() << "[通过关键字搜索历史记录] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }

        //记录结果
        dataCenter->resetSearchHistoryMessageList(pbResp->msgList());

        //通知调用者，响应处理完毕
        emit dataCenter->searchMessageDone();

        LOG() << "[通过关键字搜索历史记录] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::getHistoryMessageByTime(const QString &loginSessionId, const QString &currentChatSessionId, const QDateTime &beginTime, const QDateTime &endTime)
{
    //1.构造请求body
    my::GetHistoryMsgReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setChatSessionId(currentChatSessionId);
    pbReq.setStartTime(beginTime.toSecsSinceEpoch());
    pbReq.setOverTime(endTime.toSecsSinceEpoch());
    QByteArray body = pbReq.serialize(&serializer);

    LOG() << "[通过 时间 搜索历史记录]请求"
          << " requestId = " << pbReq.requestId()
          << " loginSessionId = " << pbReq.sessionId()
          << " currentChatSessionId = " << pbReq.chatSessionId()
          << " startTime = " << pbReq.startTime()
          << " startTime = " << pbReq.startTime();

    //2.发送http请求
    QNetworkReply* resp = this->sendHttpRequest("/service/message_storage/get_history",body);
    //3.处理响应
    connect(resp,&QNetworkReply::finished,this,[=](){
        bool ok = true;
        QString reason;
        auto pbResp = this->handleHttpResponse<my::GetHistoryMsgRsp>(resp,ok,reason);
        if(!ok)
        {
            LOG() << "[通过 时间 搜索历史记录] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }

        //记录结果
        dataCenter->resetSearchHistoryMessageList(pbResp->msgList());

        //通知调用者，响应处理完毕
        emit dataCenter->searchMessageDone();

        LOG() << "[通过 时间 搜索历史记录] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::userLogin(const QString &userName, const QString &password)
{
    //1.构造请求body
    my::UserLoginReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setNickname(userName);
    pbReq.setPassword(password);
    pbReq.setVerifyCode("");
    pbReq.setVerifyCodeId("");

    QByteArray body = pbReq.serialize(&serializer);

    LOG() << "[用户登录]请求"
          << " requestId = " << pbReq.requestId()
          << " nickname = " << pbReq.nickname()
          << " password = " << pbReq.password();

    //2.发送http请求
    QNetworkReply* resp = this->sendHttpRequest("/service/user/username_login",body);
    //3.处理响应
    connect(resp,&QNetworkReply::finished,this,[=](){
        bool ok = true;
        QString reason;
        auto pbResp = this->handleHttpResponse<my::UserLoginRsp>(resp,ok,reason);
        if(!ok)
        {
            LOG() << "[用户登录] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            emit dataCenter->userLoginDone(false,reason);
            return;
        }

        //记录结果
        dataCenter->resetLoginId(pbResp->loginSessionId());

        //通知调用者，响应处理完毕
        emit dataCenter->userLoginDone(true,"");

        LOG() << "[用户登录] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::userRegister(const QString &userName, const QString &password)
{
    //1.构造请求body
    my::UserRegisterReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setNickname(userName);
    pbReq.setPassword(password);
    pbReq.setVerifyCode("");
    pbReq.setVerifyCodeId("");

    QByteArray body = pbReq.serialize(&serializer);

    LOG() << "[用户注册]请求"
          << " requestId = " << pbReq.requestId()
          << " nickname = " << pbReq.nickname()
          << " password = " << pbReq.password();

    //2.发送http请求
    QNetworkReply* resp = this->sendHttpRequest("/service/user/username_register",body);
    //3.处理响应
    connect(resp,&QNetworkReply::finished,this,[=](){
        bool ok = true;
        QString reason;
        auto pbResp = this->handleHttpResponse<my::UserRegisterRsp>(resp,ok,reason);
        if(!ok)
        {
            LOG() << "[用户注册] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            emit dataCenter->userRegisterDone(false,reason);
            return;
        }

        //通知调用者，响应处理完毕
        emit dataCenter->userRegisterDone(true,"");

        LOG() << "[用户注册] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::phoneLogin(const QString &phone, const QString &verifyCodeId, const QString &verifyCode)
{
    //1.构造请求body
    my::PhoneLoginReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setVerifyCode(verifyCode);
    pbReq.setVerifyCodeId(verifyCodeId);
    pbReq.setPhoneNumber(phone);

    QByteArray body = pbReq.serialize(&serializer);

    LOG() << "[手机号登录]请求"
          << " requestId = " << pbReq.requestId()
          << " verifyCode = " << pbReq.verifyCode()
          << " verifyCodeId = " << pbReq.verifyCodeId()
          << " phoneNumber = " << pbReq.phoneNumber();

    //2.发送http请求
    QNetworkReply* resp = this->sendHttpRequest("/service/user/phone_login",body);
    //3.处理响应
    connect(resp,&QNetworkReply::finished,this,[=](){
        bool ok = true;
        QString reason;
        auto pbResp = this->handleHttpResponse<my::PhoneLoginRsp>(resp,ok,reason);
        if(!ok)
        {
            LOG() << "[手机号登录] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            emit dataCenter->phoneLoginDone(false,reason);
            return;
        }
        //保存
        dataCenter->resetVerifyCodeId(pbReq.verifyCodeId());

        //通知调用者，响应处理完毕
        emit dataCenter->phoneLoginDone(true,"");

        LOG() << "[手机号登录] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::phoneRegister(const QString &phone, const QString &verifyCodeId, const QString &verifyCode)
{
    //1.构造请求body
    my::PhoneRegisterReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setVerifyCode(verifyCode);
    pbReq.setVerifyCodeId(verifyCodeId);
    pbReq.setPhoneNumber(phone);

    QByteArray body = pbReq.serialize(&serializer);

    LOG() << "[手机号注册]请求"
          << " requestId = " << pbReq.requestId()
          << " verifyCode = " << pbReq.verifyCode()
          << " verifyCodeId = " << pbReq.verifyCodeId()
          << " phoneNumber = " << pbReq.phoneNumber();

    //2.发送http请求
    QNetworkReply* resp = this->sendHttpRequest("/service/user/phone_register",body);
    //3.处理响应
    connect(resp,&QNetworkReply::finished,this,[=](){
        bool ok = true;
        QString reason;
        auto pbResp = this->handleHttpResponse<my::PhoneRegisterRsp>(resp,ok,reason);
        if(!ok)
        {
            LOG() << "[手机号注册] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            emit dataCenter->phoneRegisterDone(false,reason);
            return;
        }

        //通知调用者，响应处理完毕
        emit dataCenter->phoneRegisterDone(true,"");

        LOG() << "[手机号注册] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}

void network::NetClient::getSingleFile(const QString &loginSessionId, const QString &fileId)
{
    my::GetSingleFileReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setFileId(fileId);
    pbReq.setSessionId(loginSessionId);
    LOG() << "[获取单个文件内容]请求"
          << " requestId = " << pbReq.requestId()
          << " fileId = " << pbReq.fileId()
          << " sessionId = " << pbReq.sessionId();
    QByteArray body = pbReq.serialize(&serializer);

    //发送http请求
    QNetworkReply* resp = this->sendHttpRequest("/service/file/get_single_file",body);

    //处理响应
    connect(resp,&QNetworkReply::finished,this,[=](){
        bool ok = true;
        QString reason;
        auto pbResp = this->handleHttpResponse<my::GetSingleFileRsp>(resp,ok,reason);
        if(!ok)
        {
            LOG() << "[获取单个文件内容] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }

        //直接把响回的文件,使用信号通知调用者
        emit dataCenter->getSingleFileDone(fileId,pbResp->fileData().fileContent());

        LOG() << "[获取单个文件内容] 响应接收完毕，requestId = " << pbReq.requestId();
    });

}

void network::NetClient::speechConvertText(const QString &loginSessionId, const QString &fileId, const QByteArray &speechContent)
{
    my::SpeechRecognitionReq pbReq;
    pbReq.setRequestId(makeRequestID());
    pbReq.setSessionId(loginSessionId);
    pbReq.setSpeechContent(speechContent);

    LOG() << "[语音转文字]请求"
          << " requestId = " << pbReq.requestId()
          << " sessionId = " << pbReq.sessionId();

    QByteArray body = pbReq.serialize(&serializer);

    //发送http请求
    QNetworkReply* resp = this->sendHttpRequest("/service/speech/recognition",body);

    //处理响应
    connect(resp,&QNetworkReply::finished,this,[=](){
        bool ok = true;
        QString reason;
        auto pbResp = this->handleHttpResponse<my::SpeechRecognitionRsp>(resp,ok,reason);
        if(!ok)
        {
            LOG() << "[语音转文字] 出错！ requestId = " << pbResp->requestId() << " reason = " << reason;
            return;
        }

        //直接把响回的文件,使用信号通知调用者
        emit dataCenter->speechConvertTextDone(fileId,pbResp->recognitionResult());

        LOG() << "[语音转文字] 响应接收完毕，requestId = " << pbReq.requestId();
    });
}





